using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Text.RegularExpressions;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
using System.Runtime.Remoting;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Reflection;
using MindFactorial.LaunchPoint.Runtime;
using System.Configuration;
using System.ComponentModel;
using MindFactorial.LaunchPoint.Common;
using System.Windows.Forms;
//for security lockdown
using System.Security.Principal;
using System.Security.Policy;
using System.Security;
using System.Security.Permissions;
using System.Net;
using System.Net.Sockets;
using System.ServiceModel;
using System.Windows.Markup;


namespace MindFactorial.LaunchPoint.Runtime
{
    [Serializable]
    public static class LaunchPointRuntime
    {

        static bool _run = true;
        static bool _isrootRuntime = false;
        static NotifyIconDialog _nid = null;
        static System.Windows.Threading.Dispatcher _uicontext = null;
        static LaunchPointConfiguration _launchpoint_config;
        const string PROVIDER_SECTION_NAME = "BREChannelProviders";
        public const int NOTIFICATION_PORT = 40274;       
        static RunnableComponentDomain _domain_launcher = null;

        /// <summary>
        /// Associated with the main UI thread for callback events from external system
        /// </summary>
        internal static System.Windows.Threading.Dispatcher RuntimeUIContext
        {
            get
            {
                return _uicontext;
            }
        }

        static XmlReader SchemaReader
        {
            get;
            set;
        }

        public static LaunchPointConfiguration LaunchPointConfigurationFile
        {
            get
            {
                return _launchpoint_config;
            }
        }
        

      
        
        public static void Start(string config_file_path)
        {
            #region Main Try/Catch Block
            try
            {
                Logger.Log("LaunchPoint Runtime Starting");

                //check argument length
                if (!string.IsNullOrEmpty(config_file_path))
                {
                    //read xml config
                    using (FileStream fs = File.OpenRead(config_file_path))
                    {
                        LaunchPointConfiguration config = (LaunchPointConfiguration)XamlReader.Load(fs);
                        _launchpoint_config = config;
                    }
                    LaunchApplication();
                }
                else
                {
                    throw new LaunchPointRuntimeException("5ED07408-27CA-46a7-83A4-8868E769C1FE: LaunchPoint Runtime takes one argument which should point to a valid LaunchPoint xml file with a .xaml extention.");
                }
            }
            catch (InvalidCastException invalidcast_ex)
            {
                string errorMessage = string.Format("Could not load LaunchPoint Runtime with the parameters: {0} because the root element is not a valid root element for LaunchPoint", config_file_path);
                PromptManager.Alert("D647EA9F-1A57-4e18-9677-ED2CE30F4D21:" + errorMessage);
            }
            catch (XamlParseException xaml_ex)
            {
                string errorMessage = string.Format("Could not load LaunchPoint Runtime with the parameters: {0} because the configuration file is invalid", config_file_path);
                PromptManager.Alert("279B9F4F-0553-411a-AAFD-679A4887CC35:" + errorMessage);
            }
            catch (Exception ex)
            {
                string errorMessage = string.Format("Could not load LaunchPoint Runtime with the parameters: {0} because {1}", config_file_path, ex.Message);
                PromptManager.Alert("5DBEE72A-F52C-41db-8FBB-6CD5F4402C9C:" + errorMessage);
            }
            #endregion
            
        }

        private static void LaunchApplication()
        {           
            
            //setup taskbar and ui context
            //used to display an icon in the status bar
            if (_nid == null)
            {
                _nid = new NotifyIconDialog();
            }

            //open ui thread context
            _uicontext = System.Windows.Threading.Dispatcher.FromThread(System.Threading.Thread.CurrentThread);
            Logger.Log("UI Context Set");

            string appdomain_name = string.Format("{0} with ID [{1}]", _launchpoint_config.Application.Name, Guid.NewGuid().ToString());
            //start domain launcher
            try
            {
                
                AppDomain launcher = AppDomain.CreateDomain("launcher:" + appdomain_name);
                _domain_launcher = (RunnableComponentDomain)launcher.CreateInstanceAndUnwrap("MindFactorial.LaunchPoint.Runtime", "MindFactorial.LaunchPoint.Runtime.RunnableComponentDomain");
                _domain_launcher.Run(_launchpoint_config, appdomain_name);

            }
            catch (Exception ex)
            {
                PromptManager.Alert("A88768AD-D875-4335-BA15-418A91E64B53: Unable to run application " + appdomain_name + " because " + ex.Message);
            }

            //give all applications a chance to stop after runtime is shut down
            CleanupRuntimeResources();

            
            Logger.Log("LaunchPoint runtime was stopped successfuly");          

        }


        /// <summary>
        /// Cleanup resources associated with the runtime 
        /// </summary>
        private static void CleanupRuntimeResources()
        {
            _nid.Close();
            _nid.Dispose();            
        }

        /// <summary>
        /// Shuts down the runtime
        /// </summary>
        internal static void ShutdownRuntime()
        {            
            _run = false;
            _domain_launcher.IsolatedDomain.Stop();
            _domain_launcher.IsolatedDomain.CleanupRuntimeResources();
            Application.Exit();            
        }

        /// <summary>
        /// Restarts the runtime
        /// </summary>
        internal static void Restart()
        {
            _domain_launcher.IsolatedDomain.RestartLastApp();
        }

    }

  
}
